package org.example.erat.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.erat.dto.ReportDTO;
import org.example.erat.dto.ResponseDTO;
import org.example.erat.dto.StatisticsDTO;
import org.example.erat.service.ReportAnalysisService;
import org.example.erat.service.ReportService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 实验报告控制器
 */
@RestController
@RequestMapping("/reports")
@RequiredArgsConstructor
@Slf4j
public class ReportController {

    private final ReportService reportService;
    private final ReportAnalysisService reportAnalysisService;

    /**
     * 上传实验报告
     * @param studentId 学生ID
     * @param experimentId 实验ID
     * @param file 文件
     * @return 响应
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseDTO<ReportDTO> uploadReport(
            @RequestParam Long studentId,
            @RequestParam Long experimentId,
            @RequestParam("file") MultipartFile file) {
        log.info("上传实验报告请求: studentId={}, experimentId={}, fileName={}",
                studentId, experimentId, file.getOriginalFilename());

        if (file.isEmpty()) {
            return ResponseDTO.error(400, "文件不能为空");
        }

        ReportDTO uploadedReport = reportService.uploadReport(studentId, experimentId, file);
        return ResponseDTO.success("实验报告上传成功", uploadedReport);
    }

    /**
     * 删除实验报告
     * @param id 实验报告ID
     * @return 响应
     */
    @DeleteMapping("/{id}")
    public ResponseDTO<Void> deleteReport(@PathVariable Long id) {
        log.info("删除实验报告请求: id={}", id);
        reportService.deleteReport(id);
        return ResponseDTO.success("实验报告删除成功", null);
    }

    /**
     * 获取实验报告
     * @param id 实验报告ID
     * @return 响应
     */
    @GetMapping("/{id}")
    public ResponseDTO<ReportDTO> getReport(@PathVariable Long id) {
        log.info("获取实验报告请求: id={}", id);
        ReportDTO report = reportService.getReport(id);
        return ResponseDTO.success(report);
    }

    /**
     * 获取学生的实验报告列表
     * @param studentId 学生ID
     * @return 响应
     */
    @GetMapping("/student/{studentId}")
    public ResponseDTO<List<ReportDTO>> getReportsByStudent(@PathVariable Long studentId) {
        log.info("获取学生的实验报告列表请求: studentId={}", studentId);
        List<ReportDTO> reports = reportService.getReportsByStudent(studentId);
        return ResponseDTO.success(reports);
    }

    /**
     * 获取实验的实验报告列表
     * @param experimentId 实验ID
     * @return 响应
     */
    @GetMapping("/experiment/{experimentId}")
    public ResponseDTO<List<ReportDTO>> getReportsByExperiment(@PathVariable Long experimentId) {
        log.info("获取实验的实验报告列表请求: experimentId={}", experimentId);
        List<ReportDTO> reports = reportService.getReportsByExperiment(experimentId);
        return ResponseDTO.success(reports);
    }

    /**
     * 扫描目录并分析实验报告
     * @param classId 班级ID
     * @param courseId 课程ID
     * @param directoryPath 目录路径
     * @return 响应
     */
    @PostMapping("/scan")
    public ResponseDTO<Map<String, Object>> scanAndAnalyzeReports(
            @RequestParam Long classId,
            @RequestParam Long courseId,
            @RequestParam String directoryPath) {
        log.info("扫描并分析实验报告请求: classId={}, courseId={}, directoryPath={}",
                classId, courseId, directoryPath);

        try {
            // 验证目录是否存在
            File directory = new File(directoryPath);
            if (!directory.exists()) {
                log.error("目录不存在: {}", directoryPath);
                return ResponseDTO.error(400, "目录不存在: " + directoryPath);
            }

            if (!directory.isDirectory()) {
                log.error("路径不是目录: {}", directoryPath);
                return ResponseDTO.error(400, "路径不是目录: " + directoryPath);
            }

            // 验证目录是否为空
            File[] files = directory.listFiles();
            if (files == null || files.length == 0) {
                log.error("目录为空: {}", directoryPath);
                return ResponseDTO.error(400, "目录为空: " + directoryPath);
            }

            boolean success = reportService.scanAndAnalyzeReports(classId, courseId, directoryPath);

            // 获取统计结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", success);

            // 获取实验维度统计
            List<StatisticsDTO.ExperimentStatistics> experimentStatistics = reportService.getExperimentStatistics(classId, courseId);
            result.put("experimentStatistics", experimentStatistics);

            // 获取学生维度统计
            List<StatisticsDTO.StudentStatistics> studentStatistics = reportService.getStudentStatistics(classId, courseId);
            result.put("studentStatistics", studentStatistics);

            // 获取异常信息
            Map<String, Object> analysisResult = reportAnalysisService.getLastAnalysisResult();
            if (analysisResult != null) {
                // 添加异常信息
                if (analysisResult.containsKey("invalidFileCount")) {
                    result.put("invalidFileCount", analysisResult.get("invalidFileCount"));
                }
                if (analysisResult.containsKey("unknownStudentCount")) {
                    result.put("unknownStudentCount", analysisResult.get("unknownStudentCount"));
                }
                if (analysisResult.containsKey("invalidFileNames")) {
                    result.put("invalidFileNames", analysisResult.get("invalidFileNames"));
                }
                if (analysisResult.containsKey("unknownStudents")) {
                    result.put("unknownStudents", analysisResult.get("unknownStudents"));
                }
            }

            if (success) {
                return ResponseDTO.success("实验报告扫描分析成功", result);
            } else {
                return ResponseDTO.error(400, "实验报告扫描分析失败，请检查日志获取详细信息", result);
            }
        } catch (Exception e) {
            log.error("扫描并分析实验报告异常", e);
            return ResponseDTO.error(500, "扫描并分析实验报告异常: " + e.getMessage());
        }
    }

    /**
     * 获取实验维度统计
     * @param classId 班级ID
     * @param courseId 课程ID
     * @return 响应
     */
    @GetMapping("/statistics/experiment")
    public ResponseDTO<List<StatisticsDTO.ExperimentStatistics>> getExperimentStatistics(
            @RequestParam Long classId,
            @RequestParam Long courseId) {
        log.info("获取实验维度统计请求: classId={}, courseId={}", classId, courseId);
        List<StatisticsDTO.ExperimentStatistics> statistics = reportService.getExperimentStatistics(classId, courseId);
        return ResponseDTO.success(statistics);
    }

    /**
     * 获取学生维度统计
     * @param classId 班级ID
     * @param courseId 课程ID
     * @return 响应
     */
    @GetMapping("/statistics/student")
    public ResponseDTO<List<StatisticsDTO.StudentStatistics>> getStudentStatistics(
            @RequestParam Long classId,
            @RequestParam Long courseId) {
        log.info("获取学生维度统计请求: classId={}, courseId={}", classId, courseId);
        List<StatisticsDTO.StudentStatistics> statistics = reportService.getStudentStatistics(classId, courseId);
        return ResponseDTO.success(statistics);
    }

    /**
     * 获取可视化统计数据
     * @param classId 班级ID
     * @param courseId 课程ID
     * @return 响应
     */
    @GetMapping("/statistics/visualization")
    public ResponseDTO<StatisticsDTO.VisualizationData> getVisualizationData(
            @RequestParam Long classId,
            @RequestParam Long courseId) {
        log.info("获取可视化统计数据请求: classId={}, courseId={}", classId, courseId);
        StatisticsDTO.VisualizationData visualizationData = reportService.getVisualizationData(classId, courseId);
        return ResponseDTO.success(visualizationData);
    }
}
